﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Web.Etc.PagePresent.Configuration;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.Common.Locator;

namespace Fuse8.ContentManagementFramework.Web.Etc.PagePresent
{
    /// <summary>
    /// Facade to access Page Present strategies
    /// </summary>
    public static class PagePresentStrategyFactory
    {
        static readonly ConcurrentDictionary<int, Type> Strategies = new ConcurrentDictionary<int, Type>();
        static PagePresentStrategyFactory()
        {
            var config = CmsPagePresenterConfigurationManager.PagePresenters;
            if (config != null)
            {
                foreach (CmsPagePresenterElement presenter in config.Presenters)
                {
                    Type type = Type.GetType(presenter.Type, true);
                    if (!typeof(IPagePresentStrategy).IsAssignableFrom(type))
                    {
                        throw new ConfigurationErrorsException("Type of Page Presenter with publicPageId=" +
                                                               presenter.PageId +
                                                               " does not implement IPagePresentStrategy");
                    }
                    Strategies.TryAdd(presenter.PageId, type);
                }
            }
        }

        /// <summary>
        /// Gets strategy for specified page
        /// </summary>
        /// <param name="page">Page</param>
        /// <returns></returns> 
        public static IPagePresentStrategy GetStrategy(CmsPage page)
        {
            IPagePresentStrategy strategy;
            if (Strategies.ContainsKey(page.PublicPageId))
            {
                strategy = Activator.CreateInstance(Strategies[page.PublicPageId]) as IPagePresentStrategy;
                if (strategy == null)
                {
                    throw new NotSupportedException();
                }
            }
            else
            {
                strategy = DependencyServiceLocator.Current.IsRegistered<IPagePresentStrategy>() 
                            ? DependencyServiceLocator.Current.GetInstance<IPagePresentStrategy>() 
                            : new DefaultPagePresentStrategy();
            }
            strategy.Init(page);            
            return strategy;
        }

        /// <summary>
        /// Regsiters new strategy for specified public page id
        /// </summary>
        /// <param name="publicPageId"></param>        
        public static void RegisterForPage<T>(int publicPageId) where T : IPagePresentStrategy
        {
            Strategies.TryAdd(publicPageId, typeof (T));
        }
    }
}